home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
090
/
ciarnv85.arc
/
M_DRIVER.ASM
< prev
next >
Wrap
Assembly Source File
|
1986-04-08
|
16KB
|
390 lines
page 60,132
cseg segment para public 'code'
;****************************************************************************
;* Installable device driver for XE12xx modem. This driver handles *
;* low level I/O between the host computer and the modem allowing *
;* the host program to read and write charcters to the device thru the *
;* DOS function calls that are used to read and write to a file. *
;* Take special note that when you wish to send binary data to the modem, *
;* for example, when sending voice data, you should directly store data *
;* in the data port rather than writing to the device thru DOS because *
;* the operating system will automatically cancel transmission if a 1Ah *
;* character is detected since that is ordinarily used as the end of file *
;* character. See comments in the first section of the HOST program. *
;****************************************************************************
;
; macro ( s )
;
status macro state, err, rc
ifidn <state>,<done>
or es:word ptr srh_sta_fld[bx],0100h
endif
ifidn <state>,<busy>
or es:word ptr srh_sta_fld[bx],0200h
endif
ifidn <err>,<error>
or es:word ptr srh_sta_fld[bx],1000h
endif
ifnb <rc>
or es:word ptr srh_sta_fld[bx],rc
endif
endm
;
; equates
;
; read/write
;
srh equ 0 ;static request header start
srh_len equ 13 ; " " " length
srh_len_fld equ srh ; " " " " field
srh_ucd_fld equ srh+1 ; " " " unit code field
srh_ccd_fld equ srh+2 ; " " " command code field
srh_sta_fld equ srh+3 ; " " " status field
srh_res_fld equ srh+5 ; " " " reserved area field
;
md equ srh+srh_len ;media descriptor byte
md_len equ 1 ; " " " length
dta equ md+md_len ;disk transfer address
dta_len equ 4 ;dta length
count equ dta+dta_len ;byte/sector count
count_len equ 2 ; " " length
ssn equ count+count_len ;no meaning on character device
ssn_len equ 2 ; " " " " "
;
inta00 equ 20h ; 8259 port
inta01 equ 21h ; 8259 IMR port
eoi equ 20h
livemask equ 01000101b
ctlp equ 2f9h
datap equ 2f8h
rr equ 2
xr equ 1
;
;
; media check
;
ret_byte equ md+md_len ;byte returned from driver
;
; init
;
units equ srh+srh_len ;not set by character devices
units_len equ 1
br_addr_0 equ units+units_len ;ending address
br_addr_1 equ br_addr_0+2
br_addr_len equ 4
;
;
modem proc far
start equ $
; SPECIAL DEVICE HEADER
next_dev dd -1
attribute dw 0c000h ;char device, IOCTL, IBM format
strategy dw dev_strategy ;pointer to device strategy
interrupt dw dev_int ;pointer to device interrupt handler
dev_name db 'XE1 ' ;name of character device
;*************************************************************************
;* Note the name of the device is XE1. Never name a file by that name. *
;* The name of the actual executable file is XE1D.COM. *
;*************************************************************************
;
rh_off dw ? ;request header offset
rh_seg dw ? ;request header segment
;
; FUNCTION TABLE
;
funtab label byte
dw init ;initialization
dw media_check ;media check ( block only )
dw build_bpb ;build bpb " "
dw ioctl_in ;ioctl input
dw input ;input ( read )
dw nd_input ;non_destructive input no wait ( char only )
dw in_stat ;input status " "
dw in_flush ;input flush " "
dw output ;output ( write )
dw out_verify ;output ( write ) with verify
dw out_stat ;output status " "
dw out_flush ;output flush " "
dw ioctl_out ;ioctl output
;
buff1w label word ;label for buff1 set up for word data
buff1 db 128 dup(?) ;buffer holds 64 character,status byte pairs
b1inptr dw 0 ;points to next input location in buffer
b1outptr dw 0
b1count dw 0
outcount dw 0
;****************************************************************************
;* The following interrupt routine is the secondary asynchronous *
;* communications interrupt. It is interrupt 0Bh. It is controlled by the *
;* 8259 Programmable Interrupt Controller. The IMR is at port 21h. Bit 3 *
;* enables the interrupt routine. *
;* The interrupt vector to this routine is planted in the device driver *
;* initialization routine. The initialization code is executed once at IPL *
;* time and then thrown away. Therefore the initialization routine is the *
;* last module of this program.The interrupt routine accepts any incoming *
;* characters and places them in a circular buffer updating the pointer. *
;****************************************************************************
assume cs:cseg
intname:
push ax
push dx
push di
push ds
mov ax,cs
mov ds,ax ;set ds
assume ds:cseg
cmp b1count,40h ;is buffer full
jne intn1 ;if not continue
cli ;cease interrupts
in al,inta01 ;8259 port IMR
or ax,0008h ;set bit in IMR
out inta01,al ;disallow 2nd asynch interrupts
sti ;restore interrupts
jmp intend ;if buffer full don't jam it
intn1: call charin ;get character if any
intend: mov al,eoi ;end of interrupt routine
out inta00,al ;8259 port
pop ds
pop di
pop dx
pop ax
iret
;
;
; DEVICE STRATEGY
;
assume nothing
assume cs:cseg
dev_strategy:
mov rh_seg,es ;save segment of request header pointer
mov rh_off,bx ;save offset of " " "
ret
;
; DEVICE INTERRUPT HANDLER
;
dev_int:
; preserve machine state on entry
cld
push ds
push es
push ax
push bx
push cx
push dx
push di
push si
push cs ;get ready to move cs
pop ds ;move it into ds
assume ds:cseg
;
; do the branch according to the function passed
;
mov al,es:[bx]+2 ;get function byte
rol al,1 ;get offset into table
lea di,funtab ;get address of function table
xor ah,ah
add di,ax
jmp word ptr[di]
;
; the following 2 entries are not supported by this device
;
media_check: jmp exit
build_bpb: jmp exit
;
; ioctl input
;
ioctl_in: cmp b1count,0
jz nochar ;if no characters in buffer jmp
mov di,b1outptr
mov bl,buff1+1[di] ;get status byte of that datum
and bl,not livemask
mov dx,ctlp
in al,dx ;get real status byte
and al,livemask
or al,bl ;al is resultant byte
jmp cont
nochar: mov dx,ctlp ;zero chars in buffer
in al,dx ;real status byte
and al,not rr ;nothing ready
cont: mov bx,rh_off ;restore bx as request header pointer
les di,es:dword ptr dta[bx]
;es:di points to dword adr dta
mov es:[di],al ;return ctl byte
mov es,rh_seg ;restore es:bx as request header pointer
mov es:word ptr count[bx],1 ; number bytes transferred
status done,noerror,0
jmp exit
;
; input
;
input: cmp b1count,0 ;is buffer empty
jz input ;if so loop
mov di,b1outptr ;index to buff1
mov al,buff1[di] ;get data byte from buff1
les di,es:dword ptr dta[bx]
mov es:[di],al ;store data bytes in transfer buffer
mov es,rh_seg ;restore es:bx as request header pointer
mov es:word ptr count[bx],1 ;number of bytes transferrred
dec b1count ;one less datum in buff1
inc b1outptr
inc b1outptr ;now points to next pair
and b1outptr,07Fh ;if past end of buff1 wrap around
call enable ;if buffer empty reenable interrupt
jmp in_stat ;exit thru in_stat
;
; non_destructive input no wait
;
nd_input: cmp b1count,0 ;chars in buffer ?
jz nochar2 ;if not jump
mov di,b1outptr ;index to buff1
mov al,buff1[di] ;get data byte from buff1
les di,es:dword ptr dta[bx]
mov es:[di],al ;store data byte in transfer buffer
mov es,rh_seg ;restore es:bx as request header pointer
mov es:word ptr count[bx],1 ;number bytes transferred
jmp in_stat ;exit thru in_stat
nochar2: mov es:word ptr count[bx],0 ;no bytes transferred
;exit thru in_stat
;
; input status
;
in_stat: cmp b1count,0
jz nochar3
and es:word ptr srh_sta_fld[bx],0feffh ;turn off busy bit
jmp stat1
nochar3: status busy,noerror,0 ;set busy bit
stat1: status done,noerror,0 ;set done bit in status word
jmp exit
;
; input flush
;
in_flush: mov b1count,0 ;zero counter of buff1
mov b1inptr,0 ; " pointers " "
mov b1outptr,0
call enable ;reset interrupt
jmp exit
;
; output ( write )
;
output: mov cx,es:word ptr count[bx] ;number of bytes to output
mov outcount,0 ;zero the count
cmp cx,0 ;make sure you're not about to ...
jz out_stat ;loop 65535 times, if so jump
les di,es:dword ptr dta[bx]
;make es:di point to dword transfer addr
starto: mov dx,ctlp
in al,dx ;get status
test al,xr ;is transmitter ready ?
jz starto ;if not wait
mov al,es:[di] ;put byte in al
mov dx,datap ;dx is datap
out dx,al ;output byte
inc di ;ready for next byte of transfer buffer
inc outcount ;count bytes
loop starto ;loop until all chars sent
mov es,rh_seg ;restore es:bx as request header pointer
mov ax,outcount ;get count
mov es:word ptr count[bx],ax ;return count
jmp out_stat ;exit thru out_stat
;
; output ( write ) with verify
;
out_verify: jmp output ;forget verify for now
jmp exit
;
; output status
;
out_stat: mov dx,ctlp
in al,dx ;get status
test al,xr ;is transmitter ready ?
jz tbusy ;if not set busy bit
and es:word ptr srh_sta_fld[bx],0feffh ;turn off bust bit
jmp stat4
tbusy: status busy,noerror,0 ;set busy bit
stat4: status done,noerror,0 ;set done bit
jmp exit
;
; output flush
;
out_flush: nop ;no output buffer
jmp exit
;
; ioctl output
;
ioctl_out: mov cx,es:word ptr count[bx] ;number of bytes to output
les di,es:dword ptr dta[bx] ;es:di points to transfer buffer
startc: mov al,es:[di] ;put byte in al
mov dx,ctlp ;dx is ctlp
out dx,al ;output byte
inc di ;ready for next byte
loop startc ;loop until all chars sent
mov es,rh_seg ;restore es:bx as request header pointer
status done,noerror,0 ;set status word
jmp exit
;
; re-enable interupts and check for a character already present
;
enable proc near
cmp b1count,0 ;chars in buffer ?
jnz enex ;if empty reset PIC
cli ;cease interrupts
in al,inta01 ;8259 port IMR
and ax,00f7h ;clear bit in IMR
out inta01,al ;allow 2nd asynch interrupts
;
; charin - check for incoming character and save in buffer
;
charin: mov dx,ctlp ;ctlp
in al,dx ;read status
mov ah,al ;save it
test al,rr ;check receiver ready
jz intend1 ;if not end routine
mov dx,datap ;datap
in al,dx ;read data
mov di,b1inptr ;buff1 input pointer
mov buff1w[di],ax ;store data and status
inc di ;increment index
inc di
mov b1inptr,di ;adjust pointer
and b1inptr,7Fh ;if over 127 wrap around
inc b1count ;increment character count
intend1: sti ;restore interrupts
enex: ret ;return
enable endp
;
; common exit
;
exit: pop si ;restore all of the registers
pop di
pop dx
pop cx
pop bx
pop ax
pop es
pop ds
ret
;
; init
;
init: mov es:word ptr br_addr_0[bx],offset init
mov es:br_addr_1[bx],cs
mov ax,cs ;set data segment
mov ds,ax
mov dx,offset intname
mov ax,250bh ;function 25 int b
int 21h ;plant vector
call enable
status done,noerror,0 ;set status word (done,noerror)
jmp exit
;
modem endp
cseg ends
end